package com.zhentao.datacontrol.service.impl;

import com.zhentao.datacontrol.domain.dto.DataControlRuleDTO;
import com.zhentao.datacontrol.domain.entity.ExecutionLog;
import com.zhentao.datacontrol.mapper.ExecutionLogMapper;
import com.zhentao.datacontrol.service.DataControlExecutionService;
import com.zhentao.datacontrol.service.DataControlRuleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Service
public class DataControlExecutionServiceImpl implements DataControlExecutionService {

    private static final Logger log = LoggerFactory.getLogger(DataControlExecutionServiceImpl.class);

    @Autowired
    private DataControlRuleService ruleService;

    @Autowired
    private ExecutionLogMapper executionLogMapper;

    @Override
    public String executeAutoControl() {
        String executionId = generateExecutionId();
        log.info("开始自动检控，执行ID: {}", executionId);

        try {
            // 获取所有已发布的规则
            List<DataControlRuleDTO> publishedRules = ruleService.getPublishedRules();
            log.info("查询到已发布规则数量: {}", publishedRules.size());

            if (publishedRules.isEmpty()) {
                log.warn("没有找到可执行的已发布规则，请检查规则状态");
                throw new RuntimeException("没有可执行的已发布规则，请确保有规则的发布状态为'PUBLISHED'且状态为'ENABLED'");
            }

            // 创建执行记录
            ExecutionLog executionLog = new ExecutionLog();
            executionLog.setExecutionId(executionId);
            executionLog.setExecutionType("AUTO");
            executionLog.setExecutionStatus("RUNNING");
            executionLog.setStartTime(LocalDateTime.now());
            executionLog.setTotalRecords(0);
            executionLog.setCheckedRecords(0);
            executionLog.setErrorRecords(0);
            executionLog.setWarningRecords(0);
            
            executionLogMapper.insert(executionLog);

            // 异步执行规则（这里简化为同步执行）
            executeRulesAsync(publishedRules, executionId);

            return executionId;
        } catch (Exception e) {
            log.error("自动检控执行失败", e);
            throw new RuntimeException("自动检控启动失败: " + e.getMessage());
        }
    }

    @Override
    public String executeManualControl(List<Long> ruleIds) {
        String executionId = generateExecutionId();
        log.info("开始常规检控，执行ID: {}, 规则数量: {}", executionId, ruleIds.size());

        try {
            // 获取指定的规则
            List<DataControlRuleDTO> rules = ruleIds.stream()
                    .map(ruleService::getRuleDetail)
                    .filter(rule -> rule != null && "PUBLISHED".equals(rule.getPublishStatus()))
                    .collect(java.util.stream.Collectors.toList());

            if (rules.isEmpty()) {
                throw new RuntimeException("没有可执行的规则");
            }

            // 创建执行记录
            ExecutionLog executionLog = new ExecutionLog();
            executionLog.setExecutionId(executionId);
            executionLog.setExecutionType("MANUAL");
            executionLog.setExecutionStatus("RUNNING");
            executionLog.setStartTime(LocalDateTime.now());
            executionLog.setTotalRecords(0);
            executionLog.setCheckedRecords(0);
            executionLog.setErrorRecords(0);
            executionLog.setWarningRecords(0);
            
            executionLogMapper.insert(executionLog);

            // 异步执行规则
            executeRulesAsync(rules, executionId);

            return executionId;
        } catch (Exception e) {
            log.error("常规检控执行失败", e);
            throw new RuntimeException("常规检控启动失败: " + e.getMessage());
        }
    }

    @Override
    public ExecutionLog executeRule(DataControlRuleDTO rule, String executionType) {
        String executionId = generateExecutionId();
        log.info("执行单个规则: {}, 执行ID: {}", rule.getRuleName(), executionId);

        ExecutionLog executionLog = new ExecutionLog();
        executionLog.setExecutionId(executionId);
        executionLog.setRuleId(rule.getId());
        executionLog.setRuleCode(rule.getRuleCode());
        executionLog.setExecutionType(executionType);
        executionLog.setExecutionStatus("RUNNING");
        executionLog.setStartTime(LocalDateTime.now());

        try {
            // 模拟执行过程
            Thread.sleep(1000); // 模拟执行时间

            // 模拟执行结果
            executionLog.setExecutionStatus("SUCCESS");
            executionLog.setEndTime(LocalDateTime.now());
            executionLog.setTotalRecords(1000);
            executionLog.setCheckedRecords(1000);
            executionLog.setErrorRecords(5);
            executionLog.setWarningRecords(2);
            executionLog.setDurationSeconds(1);

            executionLogMapper.insert(executionLog);
            
            return executionLog;
        } catch (Exception e) {
            log.error("规则执行失败: {}", rule.getRuleName(), e);
            executionLog.setExecutionStatus("FAILED");
            executionLog.setEndTime(LocalDateTime.now());
            executionLog.setErrorMessage(e.getMessage());
            executionLogMapper.insert(executionLog);
            return executionLog;
        }
    }

    @Override
    public List<ExecutionLog> getExecutionHistory(int pageNo, int pageSize, String executionType, String status) {
        // 这里简化实现，实际应该使用分页查询
        return executionLogMapper.selectRecentLogs(pageSize);
    }

    @Override
    public ExecutionLog getExecutionDetail(String executionId) {
        return executionLogMapper.selectByExecutionId(executionId);
    }

    @Override
    public boolean stopExecution(String executionId) {
        try {
            executionLogMapper.updateExecutionStatus(executionId, "STOPPED", 
                LocalDateTime.now().toString(), null, "用户手动停止");
            return true;
        } catch (Exception e) {
            log.error("停止执行失败: {}", executionId, e);
            return false;
        }
    }

    @Override
    public boolean cleanHistory(int keepDays) {
        try {
            String beforeDate = LocalDateTime.now().minusDays(keepDays).toString();
            int count = executionLogMapper.cleanHistoryBefore(beforeDate);
            log.info("清理了 {} 条历史记录", count);
            return true;
        } catch (Exception e) {
            log.error("清理历史记录失败", e);
            return false;
        }
    }

    @Override
    public Map<String, Object> getExecutionStatistics() {
        Map<String, Object> statistics = new HashMap<>();
        
        // 模拟统计数据
        statistics.put("totalExecutions", 150);
        statistics.put("successCount", 120);
        statistics.put("failedCount", 25);
        statistics.put("runningCount", 5);
        statistics.put("todayExecutions", 12);
        
        return statistics;
    }

    @Override
    public String retryFailedExecution(String executionId) {
        ExecutionLog originalLog = executionLogMapper.selectByExecutionId(executionId);
        if (originalLog == null) {
            throw new RuntimeException("原执行记录不存在");
        }

        // 创建新的执行ID
        String newExecutionId = generateExecutionId();
        
        // 重新执行
        ExecutionLog newLog = new ExecutionLog();
        newLog.setExecutionId(newExecutionId);
        newLog.setRuleId(originalLog.getRuleId());
        newLog.setRuleCode(originalLog.getRuleCode());
        newLog.setExecutionType(originalLog.getExecutionType());
        newLog.setExecutionStatus("RUNNING");
        newLog.setStartTime(LocalDateTime.now());
        
        executionLogMapper.insert(newLog);
        
        return newExecutionId;
    }

    /**
     * 生成执行ID
     */
    private String generateExecutionId() {
        return "EXEC_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss")) 
               + "_" + UUID.randomUUID().toString().substring(0, 8);
    }

    /**
     * 异步执行规则列表
     */
    private void executeRulesAsync(List<DataControlRuleDTO> rules, String executionId) {
        // 这里应该使用异步执行，简化为同步模拟
        new Thread(() -> {
            try {
                Thread.sleep(2000); // 模拟执行时间
                
                // 更新执行状态为成功
                executionLogMapper.updateExecutionStatus(executionId, "SUCCESS", 
                    LocalDateTime.now().toString(), 2, null);
                
                // 更新统计信息
                executionLogMapper.updateExecutionStatistics(executionId, 
                    rules.size() * 1000, rules.size() * 1000, 
                    rules.size() * 5, rules.size() * 2);
                    
            } catch (Exception e) {
                log.error("异步执行失败", e);
                executionLogMapper.updateExecutionStatus(executionId, "FAILED", 
                    LocalDateTime.now().toString(), null, e.getMessage());
            }
        }).start();
    }
}
